"""
@Author    : ghenyar
@Time      : 2025/9/5 12:54
@File      : setting
@Desc      : 有关系统设置
"""
from functools import partial

from fastapi import APIRouter, Request, Query, BackgroundTasks, Form, UploadFile, Security, Depends
from sqlalchemy.ext.asyncio import AsyncSession

from app.admin.schemas.admin import UpdateLoginAminSchema
from app.admin.schemas.settings import ChangePassword, Agreement, UpStatus
from app.admin.security import authority
from app.admin.service.admin_service import AdminService
from app.core.db import async_get_db
from app.models.configs_model import ImgsModel
from app.utils.files import FileUtils
from app.utils.redisCache import RedisCache

from app.admin.service.system_service import SystemService
from app.common.response import ApiResponse
from app.common.tools import get_password_hash, verify_password

from app.utils.jwt import JWTUtils

from app.common.commFunc import get_config as getConfigs, get_store_config

router = APIRouter()

# 鉴权
Auth = partial(Security, authority)


@router.put("/logout")
async def logout(request: Request):
    """
    退出当前登录账号
    :param request: 请求体
    :return: 退出成功
    """
    await RedisCache.delete("login_" + str(request.state.admin_id))
    return ApiResponse.success("退出成功")


@router.get("/get_info")
async def get_info(request: Request, db: AsyncSession = Depends(async_get_db)):
    """
    获取当前登录账号详细数据
    :param request: 请求体
    :param db: 数据库会话
    :return: 详细数据
    """
    admin_id = request.state.admin_id
    admin_data = await AdminService.get_login_admin_info(db, admin_id)
    return ApiResponse.result(admin_data)


@router.post("/update_admin")
async def update_admin(request: Request, data: UpdateLoginAminSchema, db: AsyncSession = Depends(async_get_db)):
    """
    修改当前登录账号信息
    :param request:  请求体
    :param data: 所需修改的数据
    :param db: 数据库会话
    :return:
    """
    admin_id = request.state.admin_id
    data = {"nickname": data.nickname, "email": data.email, "phone": data.phone, "avatar": data.avatar}
    admin = await AdminService.update_admin_dict(db, admin_id, data)
    msg = "更新信息"
    if admin is None:
        return ApiResponse.failed(f"{msg}失败")
    return ApiResponse.success(f"{msg}成功")


@router.post("/change_password")
async def change_password(changePass: ChangePassword, request: Request, db: AsyncSession = Depends(async_get_db)):
    """
    修改当前登录账号密码
    :param changePass: 修改密码请求体
    :param request: 请求体
    :param db: 数据会话
    :return:
    """
    admin_id = request.state.admin_id
    msg = "修改密码"

    # 验证旧密码
    admin = await AdminService.get_admin_by_id(db, admin_id)

    if not verify_password(changePass.old_password, admin.password):
        return ApiResponse.failed("旧密码错误")

    new_password = get_password_hash(changePass.password)

    if await AdminService.update_admin_dict(db, admin_id, {"password": new_password}):
        return ApiResponse.success(f"{msg}成功")
    return ApiResponse.failed(f"{msg}失败")


@router.get("/get_config")
async def get_config(types: str = Query(...), key: str = Query(None), db: AsyncSession = Depends(async_get_db)):
    """
    获取配置参数
    :param types: 类型
    :param key: key
    :param db: 数据库会话
    :return:
    """
    configs = await getConfigs(db, types, key)
    return ApiResponse.result(configs)


@router.post("/upload_file")
async def upload_normal_file(backTask: BackgroundTasks, file: UploadFile, path_name: str = Form(),
                             up_local: bool = True, db: AsyncSession = Depends(async_get_db)):
    """
    直接上传文件
    :param backTask:
    :param file:
    :param path_name:
    :param up_local:
    :param db:
    :return:
    """
    result = FileUtils.upload_file(file, path_name)
    if result.get("error") == 0:
        store_config = await get_store_config(db)
        if store_config and not up_local:
            # 上传至oss
            backTask.add_task(SystemService.handel_storage_file, result.get("full_path"), store_config)
        return ApiResponse.result({"file": result.get("file_name"), "original_name": result.get("original_name")},
                                  message=result.get("message"))
    else:
        return ApiResponse.failed(result.get("message"))


@router.post("/sub_up_file")
async def subsection_upload_file(chunk: UploadFile, chunkIndex: int = Form(...), fileName: str = Form(...),
                                 fileUuid: str = Form(...), file_type: str = Form(None),
                                 uuid: bool = Form(False), up_local: bool = Form(False),
                                 db: AsyncSession = Depends(async_get_db)):
    """
    分段上传文件
    :param chunk:
    :param chunkIndex:
    :param fileName:
    :param fileUuid:
    :param file_type:
    :param uuid:
    :param up_local: 是否上传至本地
    :param db: 数据库会话
    :return:
    """
    store_config = await get_store_config(db)
    if store_config and not up_local:
        file_type = "tmp"
    up_file = await FileUtils.segmentedUpload(chunk, chunkIndex, fileName, fileUuid, uuid, file_type)
    if up_file.get("code") == 200:
        return ApiResponse.result(
            {"file": up_file.get("file_name"), "original_name": up_file.get("original_name")},
            up_file.get("message"))
    else:
        return ApiResponse.failed(up_file.get("message"))


@router.post("/merge_chunks")
async def merge_chunks(request: Request, backTask: BackgroundTasks, chunks: dict,
                       db: AsyncSession = Depends(async_get_db)):
    """
    合并分段上传的文件
    :param request:
    :param backTask:
    :param chunks:
    :param db:
    :return:
    """
    result, file_path = await FileUtils.segmented_merge_chunks(chunks)
    if isinstance(result, bool) and result:
        # 获取存储配置
        store_config = await get_store_config(db)
        if store_config and not chunks.get("up_local"):
            # 上传至oss
            backTask.add_task(SystemService.handel_storage_file, file_path, store_config)
        if chunks["insert"]:
            group_id = 0 if chunks["group_id"] < 0 else chunks["group_id"]
            img = ImgsModel(name=chunks["name"], group_id=group_id, src=chunks["src"])
            db.add(img)
            await db.commit()
        return ApiResponse.success()
    return ApiResponse.failed("文件{}合并失败".format(chunks["file_name"]))


@router.put("/refresh_token", response_model=ApiResponse)
async def refresh_token(request: Request, db: AsyncSession = Depends(async_get_db)):
    """
    无感刷新token
    :param request:
    :param db:
    :return:
    """

    admin = await AdminService.get_admin_by_id(db, request.state.admin_id)

    # 生成新token
    jwt_token = JWTUtils.generate_token({'id': admin.id, 'username': admin.account})
    jwt_expire = JWTUtils.get_token_expired(jwt_token) * 1000
    key = f"login_{admin.id}"

    # 更新redis中的token及token过期时间
    login_cache = await RedisCache.get(key)
    if login_cache:
        login_cache["token"] = jwt_token
        login_cache["expire_time"] = jwt_expire
        await RedisCache.set(key, login_cache)
        return ApiResponse.result({"token": jwt_token, "expire_time": jwt_expire})
    else:
        return ApiResponse.failed()


@router.get("/admin_logs", dependencies=[Auth(scopes=["admin:log:lists"])], response_model=ApiResponse)
async def get_admin_logs(page: int = Query(1), pageSize: int = Query(10),
                         key: str = Query(None), types: int = Query(None),
                         start_time: int = Query(None), end_time: int = Query(None),
                         db: AsyncSession = Depends(async_get_db)):
    """
    操作日志列表
    :param page: 当前页码
    :param pageSize: 每页显示条数
    :param key: 关键字
    :param types: 类型
    :param start_time: 开始时间
    :param end_time: 结束时间
    :param db: 数据库会话
    :return:
    """
    result = await SystemService.log_lists(db, page, pageSize, start_time, end_time, key, types)
    return ApiResponse.page_list(result)


@router.get("/oss_list", response_model=ApiResponse)
async def get_oss_list(db: AsyncSession = Depends(async_get_db)):
    """
    存储设置列表
    :param db:
    :return:
    """
    res = await SystemService.oss_list(db)
    return ApiResponse.result(res)


@router.get("/agree_list", response_model=ApiResponse)
async def get_agree_list(db: AsyncSession = Depends(async_get_db)):
    """
    协议列表
    :param db:
    :return:
    """
    result = await SystemService.agreement_list(db)
    return ApiResponse.result(result)


@router.post("/save_agree", response_model=ApiResponse)
async def save_agree(request: Request,
                     data: Agreement,
                     db: AsyncSession = Depends(async_get_db)):
    """
    保存协议
    :param request: 请求体
    :param data: 数据
    :param db: 数据库会话
    :return:
    """
    result = await SystemService.save_agreement(db, data)
    msg="修改协议"
    if isinstance(result, bool) and result:
        return ApiResponse.success(f"{msg}成功")
    return ApiResponse.failed(f"{msg}失败！")

@router.put("/up_agree_status", response_model=ApiResponse)
async def up_agree_status(request: Request,up_status:UpStatus,db: AsyncSession = Depends(async_get_db)):
    """
    修改协议状态
    :param request: 请求体
    :param up_status: 更新状态参数
    :param db: 数据库会话
    :return:
    """
    result = await SystemService.update_agreement_statue(db, up_status.id, up_status.status)
    msg = "更新状态"
    if isinstance(result, bool) and result:
        return ApiResponse.success(f"{msg}成功")
    return ApiResponse.failed(f"{msg}失败！")
